---@class ent_alpha_rts : ent
---@field alpha_rts_selected_ent_attri alpha_rts_selected_ent_attri|nil # 右键选择的单位 属性

---@class alpha_rts_selected_ent_attri
---@field chaseandattack boolean|nil # 是否尝试追逐攻击
---@field highlight_circle ent|nil # 高亮圆形
---@field command_line ent|nil # 命令指示线

local HandleTools = require('core_alpha_rts/main/select_handle_tools')

local HT = HandleTools

local main = {}

---框选单位 动作处理器
---@param player ent
---@param mouse_x number
---@param mouse_z number
---@param tar_guid GUID|nil
function main:HandleSelect(player, mouse_x,mouse_z,tar_guid)
    if tar_guid then
        local target = c_inst(tar_guid)
        if target then
            if S_ALPHA_RTS:checkAlive(target) and target.components.combat then
                self:GroupTryAttack(player,target)
            end
        end
        self:HintLineAdjustScale(player,target,mouse_x,mouse_z)
    else
        self:GroupMoveTo(player,mouse_x,mouse_z,true)
        self:HintLineAdjustScale(player,nil,mouse_x,mouse_z)
    end
end

---获取所有框选单位
---@param player ent
---@return ent_alpha_rts[]|nil
---@nodiscard
function main:GetSelectUnits(player)
    return player.alpha_rts_selected_ent or {}
end

---所有 框选单位 执行动作
---@param player any
---@param fn fun(unit:ent_alpha_rts)
function main:EveryUnitDoAction(player,fn)
    for _,ent in ipairs(self:GetSelectUnits(player) or {}) do
        if ent.alpha_rts_selected_ent_attri == nil then
            ent.alpha_rts_selected_ent_attri = {}
        end
        fn(ent)
    end
end

---框选单位 移动
---@param player ent
---@param mouse_x number
---@param mouse_z number
---@param apply_offset_pos boolean
function main:GroupMoveTo(player,mouse_x,mouse_z,apply_offset_pos)
    self:EveryUnitDoAction(player,function (unit)
        if S_ALPHA_RTS:checkAlive(unit) then
            if unit.components.locomotor then
                local res_x,res_z = mouse_x,mouse_z
                if apply_offset_pos then
                    res_x,res_z = HT:FixTargetPoint(mouse_x,mouse_z)
                end
                local pt = Vector3(res_x,0,res_z)
                unit.components.locomotor:GoToPoint(pt)
            end
            self:GroupCancelCommandExceptMove(player)
        end
    end)
end

---框选单位 取消除了移动以外命令
---@param player ent
function main:GroupCancelCommandExceptMove(player)
    for _,ent in ipairs(self:GetSelectUnits(player) or {}) do
        if ent.alpha_rts_selected_ent_attri then
            ent.alpha_rts_selected_ent_attri.chaseandattack = nil
        end
    end
end

---框选单位 try攻击
---@param player ent
---@param target ent
function main:GroupTryAttack(player,target)
    self:EveryUnitDoAction(player,function (unit)
        if S_ALPHA_RTS:checkAlive(unit) then
            if unit.components.combat then
                -- unit.components.combat:TryAttack(target)
                unit.components.combat:SetTarget(target)
                unit.alpha_rts_selected_ent_attri.chaseandattack = true
            end
        end
    end)
end

---command 指示线
---@param player ent
---@param target ent|nil
---@param mouse_x number
---@param mouse_z number
function main:HintLineAdjustScale(player,target,mouse_x,mouse_z)
    for _,ent in ipairs(self:GetSelectUnits(player) or {}) do
        if ent.alpha_rts_selected_ent_attri and ent.alpha_rts_selected_ent_attri.command_line and ent.alpha_rts_selected_ent_attri.command_line:IsValid() then
            ent.alpha_rts_selected_ent_attri.command_line:Remove()
            ent.alpha_rts_selected_ent_attri.command_line = nil
        end

        local fx = SpawnPrefab('alpha_rts_line')
        ent.alpha_rts_selected_ent_attri.command_line = fx

        fx:DoPeriodicTask(0,function ()
            if ent and ent.alpha_rts_selected_ent_attri and ent.alpha_rts_selected_ent_attri.command_line then
                local ent_x,_,ent_z = ent:GetPosition():Get()
                fx.Transform:SetPosition(ent_x,0,ent_z)

                local tar_x,tar_z = mouse_x,mouse_z
                if target and target:IsValid() then
                    tar_x,_,tar_z = target:GetPosition():Get()
                end
                local dist = C_ALPHA_RTS:calcDist(tar_x,tar_z,ent_x,ent_z,true)
                fx.AnimState:SetScale(dist*HT.alpha_rts_line_fix_scale,1.8,1)
                fx:ForceFacePoint(tar_x,0,tar_z)
            end
        end)
    end
end

---重置选中的单位
---@param player ent
function main:ResetSelectUnits(player)
    for _,ent in ipairs(player.alpha_rts_selected_ent or {}) do
        if ent and ent.AnimState then
            ent.AnimState:SetMultColour(1,1,1,1)
        end
        if ent.alpha_rts_selected_ent_attri then
            -- 移除指示圈
            if ent.alpha_rts_selected_ent_attri.highlight_circle and ent.alpha_rts_selected_ent_attri.highlight_circle:IsValid() then
                ent.alpha_rts_selected_ent_attri.highlight_circle:Remove()
                ent.alpha_rts_selected_ent_attri.highlight_circle = nil
            end

        end
    end
    player.alpha_rts_selected_ent = {}
end

return main